using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace GameJamSnake
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public const int SCREEN_WIDTH = 1280;
        public const int SCREEN_HEIGHT = 720;

        enum ScreenState { START, PLAY, PAUSE, OVER, MENU, MENU2 };
        ScreenState m_screenState;
        KeyboardState oldState, newState;

        Tile[,] tiles;

        Segment head;
        List<Segment> snake;

        int orientation;
        int currentOrientation;
        int numSegments;
        int newX;
        int newY;
        const int START_SPEED = 350;
        const int SPEED_MINUS = 50;
        const int MAX_SPEED = 50;
        int speed = START_SPEED;
        int m_timerScore = 0;
        bool m_addSegments = false;
        bool m_addedSegments = false;
        bool m_ediblePresent;
        bool m_dead;
        bool m_stone;
        bool m_bonus;
        bool m_powerPresent;
        bool m_timePresent = false;
        float m_elapsedTime = 0;
        float spawnElapsedTime = 0.0f;

        bool m_oneKeyControl;
        float m_timePassedSinceKey;
        bool m_alreadyOnePress;

        AudioEngine audioEngine;
        WaveBank waveBank;
        SoundBank soundBank;
        Cue trackCue;
      
        Texture2D MenuTexture;
        Texture2D LargeO;
        Texture2D Small0;
        Texture2D Pause;
        Texture2D End;
        Texture2D Menu;
        Texture2D Menu2;

        VideoPlayer player = new VideoPlayer();
        bool playerstart = false;
        Video BackgroundVideo;
        Texture2D videoT;

        float large0rotation;
        float small0rotation;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            m_oneKeyControl = true;
            m_alreadyOnePress = false;
            m_timePassedSinceKey = 0;
        }
        public void Play_Sound(string CueName)
        {
            soundBank.PlayCue(CueName);
        }

        public void LoadLevel(Texture2D lvlImage)
        {
            Color[] pixels = new Color[lvlImage.Height * lvlImage.Width];
            lvlImage.GetData<Color>(pixels);

            tiles = new Tile[lvlImage.Width,lvlImage.Height];

            for (int i = 0; i < lvlImage.Height * lvlImage.Width; ++i)
            {
                int x = i % lvlImage.Width;
                int y = i / lvlImage.Width;

                Tile tempTile = new Tile(x, y);
                tempTile.Load(TextureManager.Instance.GetTex("DeadSnake"), TextureManager.Instance.GetTex("Stone"), TextureManager.Instance.GetTex("Power"), TextureManager.Instance.GetTex("Clock"));

                if (pixels[i] == Color.White)
                {
                    tempTile.EmptyTile();
                }

                if (pixels[i] == Color.Black)
                {
                    tempTile.TurnWall();
                }

                tiles[x, y] = tempTile;
            }
        }
        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            graphics.PreferredBackBufferWidth = SCREEN_WIDTH;
            graphics.PreferredBackBufferHeight = SCREEN_HEIGHT;
            graphics.ApplyChanges();

            m_screenState = ScreenState.START;

            head = new Segment(Tile.CELL_WIDTH, Tile.CELL_WIDTH,0);

            snake = new List<Segment>();

            //tiles = new Tile[SCREEN_WIDTH / Tile.CELL_WIDTH, SCREEN_HEIGHT / Tile.CELL_HEIGHT];

            //for (int i = 0; i < SCREEN_WIDTH / Tile.CELL_WIDTH; ++i)
            //{
            //    for (int j = 0; j < SCREEN_HEIGHT / Tile.CELL_WIDTH; ++j)
            //    {
            //        tiles[i, j] = new Tile(i, j);
            //    }
            //}

            numSegments = 0;

            for (int i = Segment.START_LENGTH - 1; i >= 0; --i)
            {
                ++numSegments;
                snake.Add(new Segment(i * Tile.CELL_WIDTH, 0,numSegments-1));
            }

            m_addedSegments = true;
            m_ediblePresent = false;
            m_powerPresent = false;
            m_timePresent = false;


            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            //opening vid
            BackgroundVideo = Content.Load<Video>("Images/backgroundVideo");
         
            audioEngine = new AudioEngine(@"Content\Sounds\game_Audio.xgs");
            waveBank = new WaveBank(audioEngine, @"Content\Sounds\Wave Bank.xwb");
            soundBank = new SoundBank(audioEngine, @"Content\Sounds\Sound Bank.xsb");
           

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            TextureManager.Instance.Load("Images/Head", "Head", Content);
            TextureManager.Instance.Load("Images/snake_angry", "Angry", Content);
            TextureManager.Instance.Load("Images/body", "Segment", Content);
            TextureManager.Instance.Load("Images/cloud", "DeadSnake", Content);
            TextureManager.Instance.Load("Images/snakerock", "Stone", Content);
            TextureManager.Instance.Load("Images/titlepage", "Menu", Content);
            TextureManager.Instance.Load("Images/Large0", "Large", Content);
            TextureManager.Instance.Load("Images/Small0", "Small", Content);
            TextureManager.Instance.Load("Images/smallFrog", "Power", Content);
            TextureManager.Instance.Load("Images/TestLevel", "Level", Content);
            TextureManager.Instance.Load("Images/bodycorner", "Elbow", Content);
            TextureManager.Instance.Load("Images/body", "Middle", Content);
            TextureManager.Instance.Load("Images/Pause", "Pause", Content);
            TextureManager.Instance.Load("Images/tail2", "Tail", Content);
            TextureManager.Instance.Load("Images/clock", "Clock", Content);
            TextureManager.Instance.Load("Images/marker", "Marker", Content);
            TextureManager.Instance.Load("Images/timeout", "End", Content);
            TextureManager.Instance.Load("Images/Menu2", "Menu2", Content);
            TextureManager.Instance.Load("Images/Control_Menu", "Menu1", Content);



            Scorekeeper.Instance.Load(Content);

            LoadLevel(TextureManager.Instance.GetTex("Level"));

            MenuTexture = TextureManager.Instance.GetTex("Menu");
            LargeO = TextureManager.Instance.GetTex("Large");
            Small0 = TextureManager.Instance.GetTex("Small");
            Pause = TextureManager.Instance.GetTex("Pause");
            head.Load(TextureManager.Instance.GetTex("Head"), TextureManager.Instance.GetTex("Angry"));
            End = TextureManager.Instance.GetTex("End");
            Menu2 = TextureManager.Instance.GetTex("Menu2");
            Menu = TextureManager.Instance.GetTex("Menu1");

            foreach (Segment s in snake)
            {
                s.Load(TextureManager.Instance.GetTex("Segment"));
            }

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            newState = Keyboard.GetState();

            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed
                || Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            // TODO: Add your update logic here
            switch (m_screenState)
            {
                case ScreenState.START:
                    UpdateGameStart();
                    break;

                case ScreenState.MENU:
                    if (CheckKeyPress(Keys.Enter) || CheckKeyPress(Keys.Space))
                        SwitchState("menu2");
                    break;

                case ScreenState.MENU2:
                    if (CheckKeyPress(Keys.Enter) || CheckKeyPress(Keys.Space))
                        SwitchState("start");
                    break;

                case ScreenState.PLAY:
                    if (CheckKeyPress(Keys.Enter) || CheckKeyPress(Keys.P))
                        SwitchState("pause");
                    UpdateGamePlay(gameTime);
                    break;

                case ScreenState.PAUSE:
                    if (CheckKeyPress(Keys.Enter) || CheckKeyPress(Keys.P))
                        SwitchState("play");
                    break;

                case ScreenState.OVER:
                    if (CheckKeyPress(Keys.Enter) || CheckKeyPress(Keys.P))
                        SwitchState("play");
                        Scorekeeper.Instance.resetTime();
                        Scorekeeper.Instance.resetScore();
                        LoadLevel(TextureManager.Instance.GetTex("Level"));
                        m_powerPresent = false;
                    UpdateGameOver();
                    break;
            }

            base.Update(gameTime);

            oldState = newState;
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();
          
            // TODO: Add your drawing code here
            switch (m_screenState)
            {
                case ScreenState.START:
                    DrawGameStart(spriteBatch);
                    break;

                case ScreenState.MENU:
                    Rectangle dest2 = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                    spriteBatch.Draw(Menu, dest2, dest2, Color.White);
                    break;

                case ScreenState.MENU2:
                    Rectangle dest = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                    spriteBatch.Draw(Menu2, dest, dest, Color.White);
                    break;

                case ScreenState.PLAY:
                    DrawGamePlay();
                    break;

                case ScreenState.PAUSE:
                    Rectangle dest1 = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                    spriteBatch.Draw(Pause, dest1, dest1, Color.White);
                    break;

                case ScreenState.OVER:
                    DrawGameOver();
                    break;
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }

        public void SwitchState(string state)
        {
            switch (state)
            {
                case "start":
                    m_screenState = ScreenState.START;
                    break;

                case "menu1":
                    m_screenState = ScreenState.MENU;
                    break;

                case "menu2":
                    m_screenState = ScreenState.MENU2;
                    break;

                case "play":
                    m_screenState = ScreenState.PLAY;
                    break;

                case "pause":
                    m_screenState = ScreenState.PAUSE;
                    break;

                case "over":
                    m_screenState = ScreenState.OVER;
                    break;
            }
        }

        private void UpdateGameStart()
        {
            trackCue = soundBank.GetCue("menu");
            trackCue.Play();
            if (CheckKeyPress(Keys.Enter))
            {
                trackCue = soundBank.GetCue("soundtrack");
                trackCue.Play();
                SwitchState("play");
            }
            if (CheckKeyPress(Keys.Space))
            {
                SwitchState("menu1");
            }
            large0rotation -= 0.05f;
            small0rotation -= 0.05f;
        }

        private void UpdateGamePlay(GameTime gameTime)
        {
            Scorekeeper.Instance.UpdateTime(gameTime);
            if (Scorekeeper.Instance.GameOver())
                SwitchState("over");

            if (!m_powerPresent && !head.GetPowerState())
            {
                Random rand = new Random();
                Random rand2 = new Random(rand.Next(200));

                int xCell, yCell;

                while (true)
                {
                    bool fail = false;

                    xCell = rand2.Next(SCREEN_WIDTH / Tile.CELL_WIDTH);
                    yCell = rand2.Next(SCREEN_HEIGHT / Tile.CELL_HEIGHT);

                    if (tiles[xCell, yCell].GetState() == Tile.TileState.EMPTY)
                    {
                        for (int i = 0; i < SCREEN_WIDTH / Tile.CELL_WIDTH; ++i)
                        {
                            for (int j = 0; j < SCREEN_HEIGHT / Tile.CELL_HEIGHT; ++j)
                            {
                                if (tiles[i, j].GetState() == Tile.TileState.STONE)
                                {
                                    if (tiles[i, j].GetRectangle().Intersects(tiles[xCell, yCell].GetRectangle()))
                                        fail = true;
                                }
                            }
                        }
                        if (head.GetRectangle().Intersects(tiles[xCell, yCell].GetRectangle()))
                        {
                            fail = true;
                        }
                    }
                    else
                    {
                        fail = true;
                    }

                    if (!fail)
                    {
                        tiles[xCell, yCell].PowerUp();
                        m_powerPresent = true;
                        break;
                    }
                }
            }
            if (m_timerScore >= 2000)
            {
                Random rand = new Random();
                Random rand2 = new Random(rand.Next(400));
                m_timerScore -= 2000;
                int xCell, yCell;

                while (true)
                {
                    bool fail = false;

                    xCell = rand2.Next(SCREEN_WIDTH / Tile.CELL_WIDTH);
                    yCell = rand2.Next(SCREEN_HEIGHT / Tile.CELL_HEIGHT);

                    if (tiles[xCell, yCell].GetState() == Tile.TileState.EMPTY)
                    {
                        for (int i = 0; i < SCREEN_WIDTH / Tile.CELL_WIDTH; ++i)
                        {
                            for (int j = 0; j < SCREEN_HEIGHT / Tile.CELL_HEIGHT; ++j)
                            {
                                if (tiles[i, j].GetState() == Tile.TileState.STONE)
                                {
                                    if (tiles[i, j].GetRectangle().Intersects(tiles[xCell, yCell].GetRectangle()))
                                        fail = true;
                                }
                            }
                        }
                        if (head.GetRectangle().Intersects(tiles[xCell, yCell].GetRectangle()))
                        {
                            fail = true;
                        }
                    }
                    else
                    {
                        fail = true;
                    }
                    if (!fail)
                    {
                        tiles[xCell, yCell].TimeUp();
                        //m_powerPresent = true;
                        break;
                    }
                }

                //m_timePresent = true;
            }
            /*if (m_timePresent)
            {
                // TODO: spawn timer icon
            }*/

            if (head.GetPowerState())
            {
                Scorekeeper.Instance.CountPower(gameTime);

                if (Scorekeeper.Instance.PowerOver(false))
                    head.PowerDown();
            }

            if (numSegments < 4 && m_addedSegments)
            {
                //int lastSegXPos = snake[snake.Count - 1].GetXPos();
                //int lastSegYPos = snake[snake.Count - 1].GetYPos();
                //int size = 0;
                //size += (head.GetXPos() - lastSegXPos);
                ////size *= 1;
                //size += (head.GetYPos() - lastSegYPos);
                //size *= 1;
                //if (size == 20 && ((head.GetXPos() == lastSegXPos) || (head.GetYPos() == lastSegYPos)))
                //{

                m_stone = true;
                trackCue = soundBank.GetCue("bite");
                trackCue.Play();

                int[] xRefs = new int[4];
                int[] yRefs = new int[4];

                //tiles[head.GetXReference(), head.GetYReference()].Petrify();

                xRefs[0] = head.GetXReference();
                yRefs[0] = head.GetYReference();

                int i = 1;
                foreach (Segment s in snake)
                {
                    //tiles[s.GetXReference(), s.GetYReference()].Petrify();
                    xRefs[i] = s.GetXReference();
                    yRefs[i] = s.GetYReference();
                    ++i;
                }

                int minXCell = xRefs[3];
                int maxXCell = xRefs[3];
                for (int j = 2; j >= 0; --j)
                {
                    if (xRefs[j] < minXCell)
                        minXCell = xRefs[j];

                    if (xRefs[j] > maxXCell)
                        maxXCell = xRefs[j];
                }

                int minYCell = yRefs[3];
                int maxYCell = yRefs[3];
                for (int j = 2; j >= 0; --j)
                {
                    if (yRefs[j] < minYCell)
                        minYCell = yRefs[j];

                    if (yRefs[j] > maxYCell)
                        maxYCell = yRefs[j];
                }

                tiles[minXCell, minYCell].Petrify();
                
                if ((minXCell + 2 <= Game1.SCREEN_WIDTH / Tile.CELL_WIDTH) && (minYCell + 2 <= Game1.SCREEN_HEIGHT / Tile.CELL_HEIGHT) && (tiles[minXCell + 2, minYCell + 2].GetState() == Tile.TileState.STONE) &&
                            (tiles[minXCell + 2, minYCell].GetState() == Tile.TileState.STONE) &&
                            (tiles[minXCell, minYCell + 2].GetState() == Tile.TileState.STONE))
                    {
                        tiles[minXCell + 2, minYCell + 2].EmptyTile();
                        tiles[minXCell + 2, minYCell + 2].SetMultiplyer(1);
                        tiles[minXCell + 2, minYCell].EmptyTile();
                        tiles[minXCell + 2, minYCell].SetMultiplyer(1);
                        tiles[minXCell, minYCell + 2].EmptyTile();
                        tiles[minXCell, minYCell + 2].SetMultiplyer(1);
                        tiles[minXCell, minYCell].Multiply();
                        head.Respawn(tiles);
                        if (tiles[minXCell, minYCell].GetMultiplyer() == 4)
                        {
                            MaxGrow(minXCell, minYCell);
                        }
                    }

                else if ((minXCell - 2 >= 0) && (minYCell - 2 >= 0) && (tiles[minXCell - 2, minYCell - 2].GetState() == Tile.TileState.STONE) &&
                            (tiles[minXCell - 2, minYCell].GetState() == Tile.TileState.STONE) &&
                            (tiles[minXCell, minYCell - 2].GetState() == Tile.TileState.STONE))
                    {
                        tiles[minXCell - 2, minYCell - 2].Multiply();
                        tiles[minXCell - 2, minYCell].EmptyTile();
                        tiles[minXCell - 2, minYCell].SetMultiplyer(1);
                        tiles[minXCell, minYCell - 2].EmptyTile();
                        tiles[minXCell, minYCell - 2].SetMultiplyer(1);
                        tiles[minXCell, minYCell].EmptyTile();
                        tiles[minXCell, minYCell].SetMultiplyer(1);
                        head.Respawn(tiles);
                        if (tiles[minXCell - 2, minYCell - 2].GetMultiplyer() == 4)
                        {
                            MaxGrow(minXCell - 2, minYCell - 2);
                        }
                    }

                else if ((minXCell - 2 >= 0) && (minYCell + 2 <= Game1.SCREEN_HEIGHT / Tile.CELL_HEIGHT) && (tiles[minXCell - 2, minYCell + 2].GetState() == Tile.TileState.STONE) &&
                            (tiles[minXCell, minYCell + 2].GetState() == Tile.TileState.STONE) &&
                            (tiles[minXCell - 2, minYCell].GetState() == Tile.TileState.STONE))
                    {
                        tiles[minXCell - 2, minYCell + 2].EmptyTile();
                        tiles[minXCell - 2, minYCell + 2].SetMultiplyer(1);
                        tiles[minXCell - 2, minYCell].Multiply();
                        tiles[minXCell, minYCell + 2].EmptyTile();
                        tiles[minXCell, minYCell + 2].SetMultiplyer(1);
                        tiles[minXCell, minYCell].EmptyTile();
                        tiles[minXCell, minYCell].SetMultiplyer(1);
                        head.Respawn(tiles);
                        if (tiles[minXCell - 2, minYCell].GetMultiplyer() == 4)
                        {
                            MaxGrow(minXCell - 2, minYCell);
                        }
                    }

                else if ((minXCell + 2 <= Game1.SCREEN_WIDTH / Tile.CELL_WIDTH) && (minYCell - 2 >= 0) && (tiles[minXCell + 2, minYCell - 2].GetState() == Tile.TileState.STONE) &&
                        (tiles[minXCell + 2, minYCell].GetState() == Tile.TileState.STONE) &&
                        (tiles[minXCell, minYCell - 2].GetState() == Tile.TileState.STONE))
                {
                    tiles[minXCell + 2, minYCell - 2].EmptyTile();
                    tiles[minXCell + 2, minYCell - 2].SetMultiplyer(1);
                    tiles[minXCell + 2, minYCell].EmptyTile();
                    tiles[minXCell + 2, minYCell].SetMultiplyer(1);
                    tiles[minXCell, minYCell - 2].Multiply();
                    tiles[minXCell, minYCell].EmptyTile();
                    tiles[minXCell, minYCell].SetMultiplyer(1);
                    head.Respawn(tiles);
                    if (tiles[minXCell, minYCell - 2].GetMultiplyer() == 4)
                    {
                        MaxGrow(minXCell, minYCell - 2);
                    }
                }
            }

            if (m_stone)
            {
                head.Respawn(tiles);
                ResetSegments();
                m_stone = false;
                speed = START_SPEED;
            }

            if (m_dead)
            {
                head.PowerDown();
                ResetSegments();
                head.Respawn(tiles);
                m_dead = false;
                speed = START_SPEED;
            }

            if (m_addSegments)
            {
                for (int i = Segment.START_LENGTH - 1; i >= 0; --i)
                {
                    Segment tempSeg = new Segment(head.GetXPos(), head.GetYPos(),snake.Count);
                    tempSeg.Load(TextureManager.Instance.GetTex("Segment"));
                    snake.Add(tempSeg);
                    ++numSegments;
                }

                m_addSegments = false;
            }

            if (!m_addedSegments)
            {
                spawnElapsedTime += gameTime.ElapsedGameTime.Milliseconds;
                if (spawnElapsedTime >= speed)
                {
                    m_addedSegments = true;
                    spawnElapsedTime = 0;
                }
            }

            if (!m_ediblePresent)
            {
                Random rand = new Random();
                int pos = rand.Next(numSegments);
                if (pos % 2 == 0)
                {
                    --pos;
                }

                if (pos < 3 && numSegments > 3)
                {
                    pos = 3;
                }

                if (numSegments > 3)
                {
                    snake[pos].MakeEdible();
                    m_ediblePresent = true;
                }

                //int counter = 0;
                //foreach (Segment s in snake)
                //{
                //    if (counter == pos)
                //    {
                //        s.makeEdible();
                //        ediblePresent = true;
                //        break;
                //    }

                //    ++counter;
                //}
                //pos = new Vector2(rand2.Next(), rand2.Next(400));
            }

            if (tiles[head.GetXReference(), head.GetYReference()].GetState() == Tile.TileState.DEAD && m_addedSegments)
            {
                tiles[head.GetXReference(), head.GetYReference()].EmptyTile();

                if (head.GetPowerState())
                {
                    Scorekeeper.Instance.AddScore(100);
                    m_timerScore += 100;
                }
                else
                {
                    Scorekeeper.Instance.AddScore(25);
                    m_timerScore += 25;
                    AddSegments(1);
                }
            }
            /*if (tiles[head.GetXReference(), head.GetYReference()].GetState() == Tile.TileState.TIME) // && !m_addedSegment
            {
                tiles[head.GetXReference(), head.GetYReference()].EmptyTile();
            }*/
            if (tiles[head.GetXReference(), head.GetYReference()].GetState() == Tile.TileState.WALL) // && !m_addedSegment
            {
                m_dead = true;
                foreach (Segment t in snake)
                {
                    tiles[t.GetXReference(), t.GetYReference()].Die();
                }
            }

            if (m_oneKeyControl)
            {
               m_timePassedSinceKey += gameTime.ElapsedGameTime.Milliseconds;

                if (Keyboard.GetState().IsKeyDown(Keys.Space))
                {
                    bool changeDirection = false;
                    bool turnLeft = false;
 
                    if (m_alreadyOnePress)
                    {
                        if(m_timePassedSinceKey < 500 && m_timePassedSinceKey > 250)
                        {
                            //double
                            turnLeft = true;
                            changeDirection = true;
                            m_alreadyOnePress = false;
                            m_timePassedSinceKey = 0;
                        }
                        else
                        {
                            if (m_timePassedSinceKey > 500)
                            {
                                //single
                                changeDirection = true;
                                m_alreadyOnePress = false;
                                m_timePassedSinceKey = 0;
                            }
                        }
                    }
                    else
                    {
                        m_alreadyOnePress = true;
                        m_timePassedSinceKey = 0;
                    }

                    if (changeDirection)
                    {
                        switch(orientation)
                        {
                            case 0:
                                {
                                    if (turnLeft)
                                    {
                                        orientation = 3;
                                        break;
                                    } 
                                    else
                                    {
                                        orientation = 1;
                                        break;
                                    }
                                }
                            case 1:
                                {
                                    if (turnLeft)
                                    {
                                        orientation = 2;
                                        break;
                                    }
                                    else
                                    {
                                        orientation = 0;
                                        break;
                                    }
                                }
                            case 2:
                                {
                                    if (turnLeft)
                                    {
                                        orientation = 1;
                                        break;
                                    }
                                    else
                                    {
                                        orientation = 3;
                                        break;
                                    }
                                }
                            case 3:
                                {
                                    if (turnLeft)
                                    {
                                        orientation = 2;
                                        break;
                                    }
                                    else
                                    {
                                        orientation = 0;
                                        break;
                                    }
                                }
                            default:
                                {
                                    break;
                                }
                        }
          
                    }
                }
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Left) && currentOrientation != 0)
            {
                orientation = 2;
            }

            else if (Keyboard.GetState().IsKeyDown(Keys.Right) && currentOrientation != 2)
            {
                orientation = 0;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Up) && currentOrientation != 1)
            {
                orientation = 3;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Down) && currentOrientation != 3)
            {
                orientation = 1;
            }

            m_elapsedTime += gameTime.ElapsedGameTime.Milliseconds;
            if (m_elapsedTime >= speed)
            {
                currentOrientation = orientation;
                m_elapsedTime = 0;
                head.Update(gameTime, orientation);
                newX = head.GetOldX();
                newY = head.GetOldY();

                foreach (Segment s in snake)
                {
                    s.Update(gameTime, newX, newY);
                    newX = s.GetOldX();
                    newY = s.GetOldY();
                }

                //if (m_addedSegment)
                //{
                //    m_addedSegment = false;
                //}
            }

            foreach (Segment s in snake)
            {
                if (head.GetRectangle().Intersects(s.GetRectangle()) && m_addedSegments)
                {
                    if (s.GetEdibleness())
                    {
                        trackCue = soundBank.GetCue("GoodBit");
                        trackCue.Play();
                        snake.Remove(s);

                        for (int i = 0; i < snake.Count; ++i)
                        {
                            snake[i].SetListPos(i);
                        }

                        m_ediblePresent = false;
                        --numSegments;
                        speed -= SPEED_MINUS;
                        if (speed < MAX_SPEED)
                            speed = MAX_SPEED;
                    }
                    else
                    {
                        //trackCue = soundBank.GetCue("badBit");
                        //trackCue.Play();

                        m_dead = true;
                        foreach (Segment t in snake)
                        {
                            tiles[t.GetXReference(), t.GetYReference()].Die();
                        
                        }
                    }

                    break;
                }
            }

            for (int i = 0; i < SCREEN_WIDTH / Tile.CELL_WIDTH; ++i)
            {
                for (int j = 0; j < SCREEN_HEIGHT / Tile.CELL_WIDTH; ++j)
                {
                    if (head.GetRectangle().Intersects(tiles[i, j].GetRectangle()) && m_addedSegments)
                    {
                        if (tiles[i, j].GetState() == Tile.TileState.STONE || tiles[i, j].GetState() == Tile.TileState.BONUS)
                        {
                            if (head.GetPowerState())
                            {
                                
                                tiles[i, j].EmptyTile();
                                Scorekeeper.Instance.AddScore(100 *((tiles[i,j].GetMultiplyer() * tiles[i,j].GetMultiplyer()) + tiles[i,j].GetMultiplyer() - 1));
                                m_timerScore += (100 * ((tiles[i, j].GetMultiplyer() * tiles[i, j].GetMultiplyer()) + tiles[i, j].GetMultiplyer() - 1));
                                tiles[i, j].SetMultiplyer(1);

                                //Scorekeeper.Instance.AddScore(100);
                                // TODO: Scoring
                            }
                            else
                            {
                                m_dead = true;
                                foreach (Segment s in snake)
                                {
                                    if (tiles[s.GetXReference(), s.GetYReference()].GetState() == Tile.TileState.BONUS)
                                    {
                                        m_powerPresent = false;
                                        tiles[s.GetXReference(), s.GetYReference()].EmptyTile();
                                    }
                                    if (tiles[s.GetXReference(), s.GetYReference()].GetState() != Tile.TileState.STONE &&
                                            tiles[s.GetXReference(), s.GetYReference()].GetState() != Tile.TileState.BONUS)
                                    {
                                        tiles[s.GetXReference(), s.GetYReference()].Die();
                                    }
                                }
                            }
                        }

                        if (tiles[i, j].GetState() == Tile.TileState.POWER)
                        {
                            trackCue = soundBank.GetCue("nirvana2");
                            trackCue.Play();
                            head.PowerUp();
                            tiles[i, j].EmptyTile();
                            m_powerPresent = false;
                        }

                        if (tiles[i, j].GetState() == Tile.TileState.TIME)
                        {
                            trackCue = soundBank.GetCue("nirvana2");
                            trackCue.Play();
                            Scorekeeper.Instance.IncreaseTime();
                            tiles[i, j].EmptyTile();
                            m_timePresent = false;
                        }
                    }
                }
            }
        }

        public void MaxGrow(int minXCell, int minYCell)
        {
            if ((minXCell + 4 <= Game1.SCREEN_WIDTH / Tile.CELL_WIDTH) && (minYCell + 4 <= Game1.SCREEN_HEIGHT / Tile.CELL_HEIGHT) && (tiles[minXCell + 4, minYCell + 4].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell + 4, minYCell].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell, minYCell + 4].GetState() == Tile.TileState.STONE))
            {
                tiles[minXCell + 4, minYCell + 4].EmptyTile();
                tiles[minXCell + 4, minYCell + 4].SetMultiplyer(1);
                tiles[minXCell + 4, minYCell].EmptyTile();
                tiles[minXCell + 4, minYCell].SetMultiplyer(1);
                tiles[minXCell, minYCell + 4].EmptyTile();
                tiles[minXCell, minYCell + 4].SetMultiplyer(1);
                tiles[minXCell, minYCell].Multiply();
                head.Respawn(tiles);
            }

            else if ((minXCell - 4 >= 0) && (minYCell - 4 >= 0) && (tiles[minXCell - 4, minYCell - 4].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell - 4, minYCell].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell, minYCell - 4].GetState() == Tile.TileState.STONE))
            {
                tiles[minXCell - 4, minYCell - 4].Multiply();
                tiles[minXCell - 4, minYCell].EmptyTile();
                tiles[minXCell - 4, minYCell].SetMultiplyer(1);
                tiles[minXCell, minYCell - 4].EmptyTile();
                tiles[minXCell, minYCell - 4].SetMultiplyer(1);
                tiles[minXCell, minYCell].EmptyTile();
                tiles[minXCell, minYCell].SetMultiplyer(1);
                head.Respawn(tiles);
            }

            else if ((minXCell - 4 >= 0) && (minYCell + 4 <= Game1.SCREEN_HEIGHT / Tile.CELL_HEIGHT) && (tiles[minXCell - 4, minYCell + 4].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell, minYCell + 4].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell - 4, minYCell].GetState() == Tile.TileState.STONE))
            {
                tiles[minXCell - 4, minYCell + 4].EmptyTile();
                tiles[minXCell - 4, minYCell + 4].SetMultiplyer(1);
                tiles[minXCell - 4, minYCell].Multiply();
                tiles[minXCell, minYCell + 4].EmptyTile();
                tiles[minXCell, minYCell + 4].SetMultiplyer(1);
                tiles[minXCell, minYCell].EmptyTile();
                tiles[minXCell, minYCell].SetMultiplyer(1);
                head.Respawn(tiles);
            }

            else if ((minXCell + 4 <= Game1.SCREEN_WIDTH / Tile.CELL_WIDTH) && (minYCell - 4 >= 0) && (tiles[minXCell + 4, minYCell - 4].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell + 4, minYCell].GetState() == Tile.TileState.STONE)
                    && (tiles[minXCell, minYCell - 4].GetState() == Tile.TileState.STONE))
            {
                tiles[minXCell + 4, minYCell - 4].EmptyTile();
                tiles[minXCell + 4, minYCell - 4].SetMultiplyer(1);
                tiles[minXCell + 4, minYCell].EmptyTile();
                tiles[minXCell + 4, minYCell].SetMultiplyer(1);
                tiles[minXCell, minYCell - 4].Multiply();
                tiles[minXCell, minYCell].EmptyTile();
                tiles[minXCell, minYCell].SetMultiplyer(1);
                head.Respawn(tiles);
            }
        }

        private void Transform(int minX, int maxX, int minY, int maxY)
        {
            tiles[minX, minY].SetBonus();
            tiles[minX, maxY].SetBonus();
            tiles[maxX, minY].SetBonus();
            tiles[maxX, maxY].SetBonus();
        }

        private void ResetSegments()
        {
            m_addSegments = true;
            m_addedSegments = false;
            snake.RemoveRange(0, snake.Count);
            numSegments = 0;
            m_ediblePresent = false;
        }

        private void UpdateGameOver()
        {
            if (Keyboard.GetState().GetPressedKeys().Length > 0)
                SwitchState("play");
        }

        private void DrawGameStart(SpriteBatch sb)
        {
            
            Rectangle dest = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
            Rectangle dest2 = new Rectangle(200, 200, 349, 347);
            Rectangle dest3 = new Rectangle(540, 235, 79, 76);
            Rectangle dest4 = new Rectangle(707, 235, 79, 76);
            Rectangle dest5 = new Rectangle(870, 235, 79, 76);
            Rectangle dest6 = new Rectangle(200, 200, 200, 201);
            spriteBatch.Draw(MenuTexture, dest, Color.White);
            spriteBatch.Draw(LargeO, dest2, new Rectangle(0, 0, 349, 347), Color.White, large0rotation, new Vector2(170, 171), SpriteEffects.None, 1.0f);
            //spriteBatch.Draw(Small0, dest3, new Rectangle(0, 0, 79, 76), Color.White, small0rotation+10, new Vector2(39.5f, 38), SpriteEffects.None, 1.0f);
            //spriteBatch.Draw(Small0, dest4, new Rectangle(0, 0, 79, 76), Color.White, small0rotation+20, new Vector2(39.5f, 38), SpriteEffects.None, 1.0f);
            //spriteBatch.Draw(Small0, dest5, new Rectangle(0, 0, 79, 76), Color.White, small0rotation+30, new Vector2(39.5f, 38), SpriteEffects.None, 1.0f);
            spriteBatch.Draw(LargeO, dest6, new Rectangle(0, 0, 349, 347), Color.White, large0rotation+40, new Vector2(170, 171), SpriteEffects.None, 1.0f);
        }

        private void DrawGamePlay()
        {
            
            GraphicsDevice.Clear(Color.White);

            //Draw bg video HERE!!!!
            player.Play(BackgroundVideo);
            
                videoT = player.GetTexture();

            Rectangle screen = new Rectangle(GraphicsDevice.Viewport.X, GraphicsDevice.Viewport.Y, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
            
                spriteBatch.Draw(videoT, screen, Color.White);

            head.Draw(spriteBatch, currentOrientation);

            foreach (Segment s in snake)
            {
                s.Draw(spriteBatch,snake,head,true);
            }

            for (int i = 0; i < SCREEN_WIDTH / Tile.CELL_WIDTH; ++i)
            {
                for (int j = 0; j < SCREEN_HEIGHT / Tile.CELL_WIDTH; ++j)
                {
                    tiles[i, j].Draw(spriteBatch);
                }
            }

            Scorekeeper.Instance.Draw(spriteBatch);
            /*if (m_paused)
            {
                Rectangle dest = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
                spriteBatch.Draw(Pause, dest, dest, Color.White);
            }*/
        }

        private void DrawGameOver()
        {
            Rectangle dest = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
            spriteBatch.Draw(End, dest, dest, Color.White);
        }

        private void AddSegments(int quantity)
        {
            for (int i = 0; i < quantity; ++i)
            {
                int oldLastXPos = snake[snake.Count - 1].GetXPos();
                int oldLastYPos = snake[snake.Count - 1].GetYPos();
                int newLastXPos = 0;
                int newLastYPos = 0;

                if (oldLastXPos - snake[snake.Count - 2].GetXPos() == 0)
                {
                    newLastXPos = oldLastXPos;
                    if (oldLastYPos - snake[snake.Count - 2].GetYPos() < 0)
                    {
                        newLastYPos = oldLastYPos - Tile.CELL_HEIGHT;
                        if (newLastYPos < 0)
                            newLastYPos = SCREEN_HEIGHT - Tile.CELL_HEIGHT;
                    }
                    else
                    {
                        newLastYPos = oldLastYPos + Tile.CELL_HEIGHT;
                        if (newLastYPos > SCREEN_HEIGHT - Tile.CELL_HEIGHT)
                            newLastYPos = 0;
                    }
                }
                else
                {
                    newLastYPos = oldLastYPos;
                    if (oldLastXPos - snake[snake.Count - 2].GetXPos() < 0)
                    {
                        newLastXPos = oldLastXPos - Tile.CELL_WIDTH;
                        if (newLastXPos < 0)
                            newLastXPos = SCREEN_WIDTH - Tile.CELL_WIDTH;
                    }
                    else
                    {
                        newLastXPos = oldLastXPos + Tile.CELL_WIDTH;
                        if (newLastXPos > SCREEN_WIDTH - Tile.CELL_WIDTH)
                            newLastXPos = 0;
                    }
                }

                Segment tempSeg = new Segment(newLastXPos, newLastYPos,snake.Count);
                tempSeg.Load(TextureManager.Instance.GetTex("Segment"));
                snake.Add(tempSeg);
                ++numSegments;
            }
        }

        private bool CheckKeyPress(Keys theKey)
        {
            if (newState.IsKeyUp(theKey) && oldState.IsKeyDown(theKey))
                return true;

            return false;
        }
    }
}
